﻿using MQTTnet.Client;
using MQTTnet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

namespace MqttClientDemo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //private const string EmqServerAddress = "broker.emqx.io";
        private const string EmqServerAddress = "127.0.0.1";

        public MainWindow()
        {
            InitializeComponent();

            txtSubTopic.Text = "PigeonClient/Reply";
        }

        private async void btnConnectEmq_Click(object sender, RoutedEventArgs e)
        {
            var mqttFactory = new MqttFactory();

            using (var mqttClient = mqttFactory.CreateMqttClient())
            {
                var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(EmqServerAddress).Build();
                await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);

                MessageBox.Show("连接Emq成功!");

                //注册断开连接的事件,可以在这里面处理断开重连的逻辑
                mqttClient.DisconnectedAsync += MqttClient_DisconnectedAsync;

                // This will send the DISCONNECT packet. Calling _Dispose_ without DisconnectAsync the 
                // connection is closed in a "not clean" way. See MQTT specification for more details.
                await mqttClient.DisconnectAsync(new MqttClientDisconnectOptionsBuilder()
                    .WithReason(MqttClientDisconnectOptionsReason.NormalDisconnection).Build());
            }
        }

        private async void btnPublish_Click(object sender, RoutedEventArgs e)
        {
            var mqttFactory = new MqttFactory();

            using (var mqttClient = mqttFactory.CreateMqttClient())
            {
                var mqttClientOptions = new MqttClientOptionsBuilder()
                    .WithTcpServer(EmqServerAddress)
                    .Build();

                await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);

                var applicationMessage = new MqttApplicationMessageBuilder()
                    .WithTopic("PigeonClient/WenDu")
                    .WithPayload(txtMessage.Text)
                    .Build();

                await mqttClient.PublishAsync(applicationMessage, CancellationToken.None);

                await mqttClient.DisconnectAsync();

                Debug.WriteLine("MQTT application message is published.");
            }
        }

        private async void btnSubscribe_Click(object sender, RoutedEventArgs e)
        {
            var mqttFactory = new MqttFactory();

            using (var mqttClient = mqttFactory.CreateMqttClient())
            {
                var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(EmqServerAddress).Build();




                // Setup message handling before connecting so that queued messages
                // are also handled properly. When there is no event handler attached all
                // received messages get lost.
                mqttClient.ApplicationMessageReceivedAsync += e =>
                {
                    //payload在这里取
                    var res = e.ApplicationMessage.PayloadSegment;
                    // 使用 UTF8 编码将字节数组转换为字符串
                    string utf8String = Encoding.UTF8.GetString(res.Array, res.Offset, res.Count);

                    Debug.WriteLine(utf8String);
                    Debug.WriteLine("Received application message.");

                    return Task.CompletedTask;
                };

                await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);

                var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
                    .WithTopicFilter(
                        f =>
                        {
                            f.WithTopic(txtSubTopic.Text);
                        })
                    .Build();

                await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

                Debug.WriteLine("MQTT client subscribed to topic.");
                
                while(true)
                {
                    await Task.Delay(100);
                }
            }
        }

        /// <summary>
        /// 注册断开连接的事件,可以在这里面处理断开重连的逻辑
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private Task MqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        {
            Debug.WriteLine("连接断开了，可以在这里处理重连机制!");
            return Task.CompletedTask;
        }



        /// <summary>
        /// 使用SSL证书方式连接
        /// </summary>
        private async void ConnectWithSSL()
        {
            var mqttFactory = new MqttFactory();

            using (var mqttClient = mqttFactory.CreateMqttClient())
            {
                var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("mqtt.fluux.io")
                    .WithTlsOptions(
                        o =>
                        {
                            // The used public broker sometimes has invalid certificates. This sample accepts all
                            // certificates. This should not be used in live environments.
                            o.WithCertificateValidationHandler(_ => true);
                            o.WithClientCertificates(new X509Certificate2[] { new X509Certificate2("path/to/certificate.pfx", "password") });
                            // The default value is determined by the OS. Set manually to force version.
                            o.WithSslProtocols(SslProtocols.Tls12);
                        })
                    .Build();

                using (var timeout = new CancellationTokenSource(5000))
                {
                    await mqttClient.ConnectAsync(mqttClientOptions, timeout.Token);

                    Console.WriteLine("The MQTT client is connected.");
                }
            }
        }
    }
}
